/*
	Copyright (C) 2002-2003  Luis Parravicini <luis@ktulu.com.ar>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/


package ar.com.ktulu.yenc;

import java.io.*;
import java.util.Arrays;

/**
 * Decodes files passed as command line arguments. This class is just an
 * example of how <code>ar.com.ktulu.yenc.YEncDecoder</code> works so it
 * provides minimal functionality.<br>
 * The files passed as arguments must be, either a single-part archive or
 * all the parts that compose a multi-part archive.
 *
 * @see YEncDecoder
 * @author Luis Parravicini <luis@ktulu.com.ar>
 */
public class ydecode {

	/**
	 * Sample code on how to decode multipart files. If more than one file
	 * is present in the array <code>files</code> all of them are assumed
	 * to be parts of the same archive.<br>
	 * What this method does is to scan each file and run some tests on the
	 * part number, filename and beginning/ending offsets of each part and
	 * then returns an array of the files in the order they should be read
	 * to decompress the archive.
	 * <strong>Note:</strong> For simplicity it's assumed each file
	 * contains only a part of the archive.
	 */
	public String[] sortFiles(YEncDecoder decoder, String[] files)
	throws IOException, YEncException {
		if (files.length == 1) {
			String[] f = { files[0] };
			return f;
		}

		Part[] parts = new Part[files.length];
		int i;

		// get info on all parts
		for (i = 0; i < files.length; i++) {
			decoder.reset();
			decoder.setInputStream(new BufferedInputStream(
				new FileInputStream(files[i])));
			parts[i] = new Part();
			parts[i].file = files[i];
			parts[i].name = decoder.getFileName();
			parts[i].part = decoder.getPartNumber();
			parts[i].pbegin = decoder.getPartBegin();
			parts[i].pend = decoder.getPartEnd();
		}
		// sort the parts and check if the offsets are correct
		Arrays.sort(parts);
		for (i = 0; i < parts.length-1; i++) {
			if (parts[i].part+1 != parts[i+1].part)
				throw new MissingPartsException("Parts are " +
					"not consecutive (expecting=" +
					(parts[i].part + 1) + "/read=" +
					parts[i+1].part + ")");
			if (!parts[i].name.equals(parts[i+1].name))
				throw new YEncException("Parts are from " +
					"different archives");
			if (parts[i].pend+1 != parts[i+1].pbegin)
				throw new YEncException("Missing data");
		}
		// return the filenames in the correct order
		String[] ofiles = new String[parts.length];
		for (i = 0; i < ofiles.length; i++)
			ofiles[i] = parts[i].file;
		return ofiles;
	}

	class Part implements Comparable {
		String file, name;
		int part;
		long pbegin, pend;

		/**
		 * Note: this class has a natural ordering that is inconsistent
		 * with equals.
		 */
		public int compareTo(Object o) {
			if (!(o instanceof Part))
				throw new ClassCastException("object is not " +
					"instance of Part");
			Part po = ((Part)o);

			if (part < po.part) return -1;
			if (part > po.part) return 1;
			return 0;
		}
	}

	public static void main(String[] args)
	throws IOException, FileNotFoundException, YEncException {
		if (args.length == 0) {
			System.out.println("usage: ar.com.ktulu.yenc.ydecode" +
				" [-d] ENCODED_FILE...");
			return;
		}

		long begin = System.currentTimeMillis();

		YEncDecoder decoder = new YEncDecoder();
		try {
			boolean debug = false;
			if (args[0].equals("-d")) {
				debug = true;
				String[] args2 = new String[args.length-1];
				System.arraycopy(args, 1, args2, 0,
					args.length-1);
				args = args2;
				if (args.length == 0) {
					System.out.println("usage: " +
						"ar.com.ktulu.yenc.ydecode" +
						" [-d] ENCODED_FILE...");
					return;
				}

			}
			decoder.debugMessages(debug);

			String[] files = new ydecode().sortFiles(decoder, args);
			OutputStream out = null;
			for (int i = 0; i < files.length; i++) {
				decoder.setInputStream(new BufferedInputStream(
					new FileInputStream(files[i])), true);
				System.out.print("decoding file \"" +
					decoder.getFileName() +
					"\" [" + decoder.getSize() + " bytes]");
				if (decoder.getPartNumber() != -1)
					System.out.print(" (" +
						decoder.getPartNumber() + "/" +
						decoder.getTotalParts() + ")");
				System.out.println();
				if (out == null) {
					out = new BufferedOutputStream(
						new FileOutputStream(
							decoder.getFileName()));
					decoder.setOutputStream(out);
				}
				decoder.decode();
			}
			long elapsed = System.currentTimeMillis() - begin;
			String selapsed;
			if (elapsed > 1000)
				selapsed = elapsed/1000 + " secs.";
			else
				selapsed = elapsed + " msecs.";
			System.out.println("file decompressed in "+selapsed);
		} catch (YEncException e) {
			System.err.println(e.getMessage());
		}
	}

}
